package com.tjcd.project.library_base.common.utils;

import android.annotation.SuppressLint;
import android.text.TextUtils;

import org.jetbrains.annotations.NotNull;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * @Author jiangKunKun
 * @CreateDate 2022/3/31
 * @Description
 * @SpittingGrooves
 */
public class TimeUtil {
    /**
     * one day millisecond count
     */
    public static final long ONE_DAY_MILLISECONDS = 1000 * 3600 * 24;

    public static final long ONE_HOUR_MILLISECONDS = 1000 * 3600;

    public static final long ONE_MIN_MILLISECONDS = 1000 * 60;

    /**
     * 时间日期格式化到年月日时分秒.
     */
    public static String dateFormatYMDHMS = "yyyy-MM-dd HH:mm:ss";
    public static String dateFormatYMDHMS_f = "yyyyMMddHHmmss";
    public static String dateFormatMDHM = "MM-dd HH:mm";
    public static String dateFormat = "yyyy-MM-dd HH:mm";
    /**
     * 时间日期格式化到年月日.
     */
    public static String dateFormatYMD = "yyyy-MM-dd";

    /**
     * 时间日期格式化到年月日时分.中文显示
     */
    public static String dateFormatYMDHMofChinese = "yyyy年MM月dd日 HH:mm";

    /**
     * 时间日期格式化到年月日.中文显示
     */
    public static String dateFormatYMDofChinese = "yyyy年MM月dd日";
    /**
     * 时间日期格式化到月日.中文显示
     */
    public static String dateFormatMDofChinese = "MM月dd日";
    /**
     * 时间日期格式化到月.中文显示
     */
    public static String dateFormatMofChinese = "MM月";
    /**
     * 时间日期格式化到年月.
     */
    public static String dateFormatYM = "yyyy-MM";

    /**
     * 时间日期格式化到年月日时分.
     */
    public static String dateFormatYMDHM = "yyyy-MM-dd HH:mm";

    /**
     * 时间日期格式化到月日.
     */
    public static String dateFormatMD = "MM/dd";
    public static String dateFormatM_D = "MM-dd";

    public static String dateFormatM = "MM月";
    public static String dateFormatD = "dd";
    public static String dateFormatM2 = "MM";

    public static String dateFormatMDHMofChinese = "MM月dd日HH时mm分";
    public static String dateFormatHMofChinese = "HH时mm分";

    /**
     * 时分秒.
     */
    public static String dateFormatHMS = "HH:mm:ss";

    /**
     * 时分.
     */
    public static String dateFormatHM = "HH:mm";

    /**
     * 上午/下午时分
     */
    public static String dateFormatAHM = "aHH:mm";

    public static String dateFormatYMDE = "yyyy/MM/dd E";
    public static String dateFormatYMD2 = "yyyy/MM/dd";

    private final static ThreadLocal<SimpleDateFormat> dateFormater = new ThreadLocal<SimpleDateFormat>() {
        @SuppressLint("SimpleDateFormat")
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    @SuppressLint("SimpleDateFormat")
    private final static ThreadLocal<SimpleDateFormat> dateFormater2 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    /**
     * 描述：计算两个日期所差的天数.
     *
     * @param date1 第一个时间的毫秒表示
     * @param date2 第二个时间的毫秒表示
     * @return int 所差的天数
     */
    public static int getOffectDay(long date1, long date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTimeInMillis(date2);
        //先判断是否同年
        int y1 = calendar1.get(Calendar.YEAR);
        int y2 = calendar2.get(Calendar.YEAR);
        int d1 = calendar1.get(Calendar.DAY_OF_YEAR);
        int d2 = calendar2.get(Calendar.DAY_OF_YEAR);
        int maxDays = 0;
        int day = 0;
        if (y1 - y2 > 0) {
            maxDays = calendar2.getActualMaximum(Calendar.DAY_OF_YEAR);
            day = d1 - d2 + maxDays;
        } else if (y1 - y2 < 0) {
            maxDays = calendar1.getActualMaximum(Calendar.DAY_OF_YEAR);
            day = d1 - d2 - maxDays;
        } else {
            day = d1 - d2;
        }
        return day;
    }

    /**
     * 描述：计算两个日期所差的小时数.
     *
     * @param date1 第一个时间的毫秒表示
     * @param date2 第二个时间的毫秒表示
     * @return int 所差的小时数
     */
    public static int getOffectHour(long date1, long date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTimeInMillis(date2);
        int h1 = calendar1.get(Calendar.HOUR_OF_DAY);
        int h2 = calendar2.get(Calendar.HOUR_OF_DAY);
        int h = 0;
        int day = getOffectDay(date1, date2);
        h = h1 - h2 + day * 24;
        return h;
    }

    /**
     * 描述：计算两个日期所差的分钟数.
     *
     * @param date1 第一个时间的毫秒表示
     * @param date2 第二个时间的毫秒表示
     * @return int 所差的分钟数
     */
    public static int getOffectMinutes(long date1, long date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTimeInMillis(date2);
        int m1 = calendar1.get(Calendar.MINUTE);
        int m2 = calendar2.get(Calendar.MINUTE);
        int h = getOffectHour(date1, date2);
        int m = 0;
        m = m1 - m2 + h * 60;
        return m;
    }

    /**
     * 获取 已当前周为基础的前几周或后几周的开始和结束时间
     * @param isStart true 开始时间 false 结束时间
     * @return
     */
    public static String getAweekStartAndEndTime(boolean isStart) {
        return getAweekStartAndEndTime(0,isStart);
    }

    /**
     * 获取 已当前周为基础的前几周或后几周的开始和结束时间
     * @param burdenWeek 前几周 负数  后几周 整数
     * @param isStart true 开始时间 false 结束时间
     * @return
     */
    public static String getAweekStartAndEndTime(int burdenWeek, boolean isStart) {
        Calendar cal = Calendar.getInstance();
        int week = cal.get(Calendar.WEEK_OF_YEAR);
        if ((week + burdenWeek) <= 0){
            cal.set(Calendar.YEAR, cal.getWeekYear() - 1);
            week = (week + 52) + burdenWeek;
        }else {
            week = week + burdenWeek;
        }
        cal.set(Calendar.WEEK_OF_YEAR, week);
        String date = "";
        if (isStart){
            date = getStartDayOfWeekNo(cal.get(Calendar.YEAR), cal.get(Calendar.WEEK_OF_YEAR));
        }else {
            date = getEndDayOfWeekNo(cal.get(Calendar.YEAR), cal.get(Calendar.WEEK_OF_YEAR));
        }
        return date;
    }

    /**
     * get Calendar of given year
     * @param year
     * @return
     */
    private static Calendar getCalendarFormYear(int year){
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        cal.set(Calendar.YEAR, year);
        return cal;
    }

    /**
     * get start date of given week no of a year
     * @param year
     * @param weekNo
     * @return
     */
    public static String getStartDayOfWeekNo(int year, int weekNo){
        Calendar cal = getCalendarFormYear(year);
        cal.set(Calendar.WEEK_OF_YEAR, weekNo);
        return cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" +
                cal.get(Calendar.DAY_OF_MONTH);

    }

    /**
     * get the end day of given week no of a year.
     * @param year
     * @param weekNo
     * @return
     */
    public static String getEndDayOfWeekNo(int year, int weekNo){
        Calendar cal = getCalendarFormYear(year);
        cal.set(Calendar.WEEK_OF_YEAR, weekNo);
        cal.add(Calendar.DAY_OF_WEEK, 6);
        return cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" +
                cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取某段时间内的所有日期 月份
     * @param start 开始日期
     * @param end 结束日期
     * @return
     */
    public static List<String> getPeriodMonths(String start, String end) {
        SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMD);
        Date dStart = null;
        Date dEnd = null;
        try {
            dStart = mSimpleDateFormat.parse(start);
            dEnd = mSimpleDateFormat.parse(end);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        List dateList = new ArrayList();
        Calendar dd = Calendar.getInstance();//定义日期实例
        dd.setTime(dStart);//设置日期起始时间
        dateList.add(mSimpleDateFormat.format(dd.getTime()));
        while (dd.getTime().before(dEnd)) {//判断是否到结束日期
            dd.add(Calendar.MONTH, 1);//进行当前日期月份加1
            dateList.add(mSimpleDateFormat.format(dd.getTime()));
        }
        return dateList;
    }

    /**
     * 获取某段时间内的所有日期
     * @param start 开始日期
     * @param end 结束日期
     * @return
     */
    public static List<String> findDates(String start, String end) {
        SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMD);
        Date dStart = null;
        Date dEnd = null;
        try {
            dStart = mSimpleDateFormat.parse(start);
            dEnd = mSimpleDateFormat.parse(end);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar cStart = Calendar.getInstance();
        cStart.setTime(dStart);

        List dateList = new ArrayList();
        //别忘了，把起始日期加上
        dateList.add(mSimpleDateFormat.format(dStart));
        // 此日期是否在指定日期之后
        while (dEnd.after(cStart.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            cStart.add(Calendar.DAY_OF_MONTH, 1);
            dateList.add(mSimpleDateFormat.format(cStart.getTime()));
        }
        if (dateList.size() > 0){
            dateList.remove(dateList.size() - 1);
        }
        return dateList;
    }

    /**
     * 得到某一天是这一年的第几周
     * @param date
     * @return
     */
    public static int getWhichWeek(String date)  {
        SimpleDateFormat format = new SimpleDateFormat(dateFormatYMD);
        Calendar cal = Calendar.getInstance();
        try {
            cal.setTime(format.parse(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int week = cal.get(Calendar.WEEK_OF_YEAR);
        return week;
    }

    /**
     * 获取当年的开始时间或结束时间
     * @param isStart true开始 false结束
     * @return
     */
    public static Date getYearStartAndEnd(boolean isStart) {
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        if (isStart){
            calendar.add(Calendar.YEAR, 0);
            calendar.add(Calendar.DATE, 0);
            calendar.add(Calendar.MONTH, 0);
            calendar.set(Calendar.DAY_OF_YEAR, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
        }else {
            int year = calendar.get(Calendar.YEAR);
            calendar.clear();
            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
            calendar.roll(Calendar.DAY_OF_YEAR, -1);
        }
        return calendar.getTime();
    }

    /**
     * 获取本月的开始和结束时间
     * @param isStart true开始 false结束
     * @return
     */
    public static String getMonthStartAndEnd(boolean isStart) {
        // 获取当前年份、月份、日期
        Calendar cale = Calendar.getInstance();
        SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMD);
        if (isStart){
            cale.add(Calendar.MONTH, 0);
            cale.set(Calendar.DAY_OF_MONTH, 1);
        }else {
            cale.add(Calendar.MONTH, 1);
            cale.set(Calendar.DAY_OF_MONTH, 0);
        }
        return mSimpleDateFormat.format(cale.getTime());
    }

    /**
     * 获取以前的月份
     * @param month 要减去或加上的几个月
     * @return
     */
    public static String getAssignMonth(int month) {
        Calendar c = Calendar.getInstance();
        SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMD);
        c.setTime(new Date());
        c.add(Calendar.MONTH, month);
        return mSimpleDateFormat.format(c.getTime());
    }


    /**
     * 描述：根据时间返回几天前或几分钟的描述.
     *
     * @param strDate the str date
     * @return the string
     */
    public static String formatDateStr2Desc(String strDate) {
        DateFormat df = new SimpleDateFormat(dateFormatYMDHMS);
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        String ftime = "";
        try {
            c2.setTime(df.parse(strDate));
            c1.setTime(new Date());
            int d = getOffectDay(c1.getTimeInMillis(), c2.getTimeInMillis());
            if (d == 0) {
                int h = getOffectHour(c1.getTimeInMillis(), c2.getTimeInMillis());
                if (h > 0) {
                    ftime = h + "小时前";
                } else if (h < 0) {
                    ftime = Math.abs(h) + "小时后";
                } else if (h == 0) {
                    int m = getOffectMinutes(c1.getTimeInMillis(), c2.getTimeInMillis());
                    if (m > 0) {
                        ftime = m + "分钟前";
                    } else if (m < 0) {
                        ftime = Math.abs(m) + "分钟后";
                    } else {
                        ftime = "刚刚";
                    }
                }
            } else if (d > 0) {
                if (d == 1) {
                    ftime = "昨天";
                } else if (d == 2) {
                    ftime = "前天";
                }
            } else if (d < 0) {
                if (d == -1) {
                    ftime = "明天";
                } else if (d == -2) {
                    ftime = "后天";
                }
                ftime =  Math.abs(d) + "天后";
            }

        } catch (Exception e) {
        }
        return ftime;
    }

    /**
     * 以友好的方式显示时间
     *
     * @param ms
     * @return
     */
    public static String getFriendlyTime(@NotNull Long ms) {
        Date time = new Date();
        time.setTime(ms);

        String ftime = "";
        Calendar cal = Calendar.getInstance();

        // 判断是否是同一天
        String curDate = dateFormater2.get().format(cal.getTime());
        String paramDate = dateFormater2.get().format(time);
        if (curDate.equals(paramDate)) {
            int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000);
            if (hour == 0) {
                if (((cal.getTimeInMillis() - time.getTime()) / 60000) < 1) {
                    ftime = "刚刚";
                } else {
                    ftime = Math.max((cal.getTimeInMillis() - time.getTime()) / 60000, 1) + "分钟前";
                }
            } else {
                ftime = hour + "小时前";
            }
            return ftime;
        }

        long lt = time.getTime() / 86400000;
        long ct = cal.getTimeInMillis() / 86400000;
        int days = (int) (ct - lt);
        if (days == 0) {
            int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000);
            if (hour == 0) {
                ftime = Math.max(
                        (cal.getTimeInMillis() - time.getTime()) / 60000, 1)
                        + "分钟前";
            } else {
                ftime = hour + "小时前";
            }
        } else if (days == 1) {
            ftime = "昨天";
        } else if (days == 2) {
            ftime = "前天";
        } else if (days > 2 && days <= 10) {
            ftime = days + "天前";
        } else if (days > 10) {
            ftime = dateFormater2.get().format(time);
        }
        return ftime;
    }

    /**
     * 计算年龄
     * @param dateOfBirth 出生日期
     * @return
     */
    public static int getAgeByBirthday(@NotNull Date dateOfBirth) {
        Calendar cal = Calendar.getInstance();
        if (cal.before(dateOfBirth)) { // 出生日期晚于当前时间，无法计算
            return 0;
        }
        int yearNow = cal.get(Calendar.YEAR);  // 当前年份
        int monthNow = cal.get(Calendar.MONTH);  // 当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); // 当前日期
        cal.setTime(dateOfBirth);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;   // 计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--; // 当前日期在生日之前，年龄减一
                }
            } else {
                age--; // 当前月份在生日之前，年龄减一
            }
        }
        return age;
    }

    /**
     * 时长  几天或几小时或几分钟或几秒
     * @param duration
     * @return
     */
    public static String getFriendTimeOffer(long duration) {
        int day = (int) (duration / (24 * 60 * 60 * 1000));
        if (day > 0) {
            return day + "天";
        }
        int time = (int) (duration / (60 * 60 * 1000));
        if (time > 0) {
            return time + "小时";
        }
        int min = (int) (duration / (60 * 1000));
        if (min > 0) {
            return min + "分钟";
        }
        int sec = (int) duration / 1000;
        if (sec > 0) {
            return sec + "秒";
        }
        return "1秒";
    }

    /**
     * 两个日期比较大小 默认 yyyy-MM-dd HH:mm:ss
     * @param date1 时间1
     * @param date2 时间2
     * @return 1. 时间1大 -1. 时间2大 0. 相等 -2. 未知错误
     */
    public static int compareDate(@NotNull String date1, @NotNull String date2) {
        return compareDate(date1, date2);
    }

    /**
     * 两个日期比较大小
     * @param date1 时间1
     * @param date2 时间2
     * @param timeFormat 时间格式  默认 yyyy-MM-dd HH:mm:ss 例如 yyyy只比较年份 yyyy-MM只比较年月 yyyy-MM-dd只比较年月日
     * @return 1. 时间1大 -1. 时间2大 0. 相等 -2. 未知错误
     */
    public static int compareDate(@NotNull String date1, @NotNull String date2, String timeFormat) {
        DateFormat df = new SimpleDateFormat(TextUtils.isEmpty(timeFormat) ? dateFormatYMDHMS : timeFormat, Locale.CHINA);
        try {
            Date dt1 = df.parse(date1);
            Date dt2 = df.parse(date2);
            if (dt1.getTime() - dt2.getTime() > 0) {
                return 1;
            } else if (dt2.getTime() - dt1.getTime() > 0){
                return -1;
            }else {
                return 0;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return -2;
    }

    /**
     * 获取 当天距离的天数
     * @param day -1=昨天  -2=前天  0=当前天  1=明天  2=后天
     * @return
     */
    public static String getDistanceDayTime(int day){
        SimpleDateFormat format = new SimpleDateFormat(dateFormatYMD);
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, day);
        return format.format(cal.getTime());
    }

    /**
     * 给时间加几个小时
     * @param specifiedTime 指定时间
     * @param hour 要添加的小时数
     * @return
     */
    public static String addDateMinut(@NotNull String specifiedTime, int hour) {
        SimpleDateFormat format = new SimpleDateFormat(dateFormatYMDHMS);
        Date date = null;
        try {
            date = format.parse(specifiedTime);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, hour);// 24小时制
        return format.format(cal.getTime());
    }

    /**
     * @param nowTime   当前时间
     * @param startTime	开始时间
     * @param endTime   结束时间
     * @return
     * @author sunran   判断当前时间在时间区间内
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 计算工龄
     * @param entryDate 入职日期
     * @return 工龄
     */
    public static String getWorkingAge(String entryDate) {
        SimpleDateFormat format = new SimpleDateFormat(dateFormatYMD);
        Date date = null;
        try {
            date = format.parse(entryDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Calendar cal = Calendar.getInstance();
        if (cal.before(date)) { // 出生日期晚于当前时间，无法计算
            return "出生日期晚于当前时间，无法计算";
        }
        int yearNow = cal.get(Calendar.YEAR);  // 当前年份
        int monthNow = cal.get(Calendar.MONTH);  // 当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); // 当前日期
        cal.setTime(date);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int year = yearNow - yearBirth; // 计算整岁数
        int month = monthNow - monthBirth;
        int day = dayOfMonthNow - dayOfMonthBirth;

        if (day < 0) {
            month--;
            Calendar today = Calendar.getInstance();
            today.set(Calendar.DAY_OF_MONTH, 1);
            today.add(Calendar.DAY_OF_MONTH, -1);
            day += today.get(Calendar.DAY_OF_MONTH);
        }

        if (month < 0) {
            year--;
            month += 12;
        }

        StringBuffer sb = new StringBuffer();
        if (year > 0) {
            sb.append(year).append("年");
        }
        if (month > 0) {
            sb.append(month).append("个月");
        }
        if (day > 0) {
            sb.append(day).append("天");
        }
        return sb.toString();
    }
}
